/*
 * JVM_OpcodeArray.c
 *
 *  Created on: 05.01.2011
 *      Author: Tavin
 */

#include <stdint.h>

#include "JVM_StatusCodes.h"
#include "JVM_Opcode.h"
#include "JVM_OpcodeArray.h"
#include "JVM_Handle.h"

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_iaload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_iaload() {
	int32_t value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetInt(handleNumber, index, &value);

	JVM_Opcode_pushIntValue(value);
	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_laload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_laload() {
	int64_t value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0 )
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetLong(handleNumber, index, &value);

	JVM_Opcode_pushLongValue(value);

	return (STCD_OK);
	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_faload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_faload() {
	float value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetFloat(handleNumber, index, &value);

	JVM_Opcode_pushFloatValue(value);

	return (STCD_OK);
	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_daload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_daload() {
	double value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetDouble(handleNumber, index, &value);

	JVM_Opcode_pushDoubleValue(value);

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_aaload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_aaload() {

	uint32_t index;
	JVM_HandleNumber_t handleNumber;
	JVM_HandleNumber_t reference;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetReference(handleNumber, index, &reference);

	JVM_Opcode_pushReference(reference);

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_baload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_baload() {
	int8_t value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetByte(handleNumber, index, &value);

	JVM_Opcode_pushByteValue(value);

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_caload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.6			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_caload() {
	int16_t value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetShort(handleNumber, index, &value);

	JVM_Opcode_pushCharValue(value);

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_saload								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_saload() {
	int16_t value;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0 )
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arrayGetShort(handleNumber, index, &value);

	JVM_Opcode_pushShortValue(value);

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_iastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_iastore() {
	uint32_t index;
	uint32_t value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popIntValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetInt(handleNumber, index, value);
	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_lastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_lastore() {
	uint32_t index;
	uint64_t value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popLongValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0 )
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetLong(handleNumber, index, value);
	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_fastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_fastore() {
	uint32_t index;
	float value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popFloatValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetFloat(handleNumber, index, value);
	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_dastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_dastore() {
	uint32_t index;
	double value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popDoubleValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetDouble(handleNumber, index, value);
	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_aastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_aastore() {
	JVM_HandleNumber_t reference;
	uint32_t index;
	JVM_HandleNumber_t handleNumber;

	reference = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (reference == 0)
		return (STCD_NULL_REFERENCE);

	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	JVM_Handle_arraySetReference(handleNumber, index, reference);

	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_bastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_bastore() {
	uint32_t index;
	uint32_t value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popIntValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetByte(handleNumber, index, value);

	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_castore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_castore() {
	uint32_t index;
	uint32_t value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popIntValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0)
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetShort(handleNumber, index, value);

	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_sastore								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_sastore() {
	uint32_t index;
	uint32_t value;
	JVM_HandleNumber_t handleNumber;

	value = JVM_Opcode_popIntValue();
	index = JVM_Opcode_popIntValue();

	handleNumber = JVM_Opcode_popReference();

	// NEW return code for EXCEPTION -> NULL
	if (handleNumber == 0 )
		return (STCD_NULL_REFERENCE);

	JVM_Handle_arraySetShort(handleNumber, index, value);

	return (STCD_OK);
	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_newarray								Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_newarray() {
	//	uint16_t MemorySize;
	uint8_t arrayType;
	uint32_t count;
	//	JVM_HandleNumber_t handleNumber;

	arrayType = JVM_Opcode_getCodeByte();

	count = JVM_Opcode_popIntValue();
	if (count < 0)
		return (STCD_NEGATIVE_ARRAY_SIZE);

	/*
	 switch (arrayType)
	 {
	 case T_SHORT:
	 case T_CHAR:
	 MemorySize=count<<1;
	 break;

	 case T_INT:
	 case T_FLOAT:
	 MemorySize=count<<2;
	 break;

	 case T_LONG:
	 case T_DOUBLE:
	 MemorySize=count<<3;
	 break;

	 case  T_BOOLEAN	:
	 case T_BYTE:
	 MemorySize=count;
	 break;


	 default:
	 return(STCD_UNKNOWN_ARRAY_TYPE);
	 }




	 handleNumber=JVM_Handle_newArray(MemorySize,0); //TODO ClassPointer

	 JVM_Handle_arraySetLenght(handleNumber,count);
	 // TODO Clear Array
	 */
	JVM_Opcode_pushReference(makePrimitiveArray(count, 0, arrayType));

	return (STCD_OK);
}
/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_anewarray							Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_anewarray() {
	//	uint16_t MemorySize;
	uint16_t arrayClassIndex;
	uint32_t count;
	//	JVM_HandleNumber_t handleNumber;
	JVM_StackFrame_t * myStackFrame;
	JVM_Class_t *myClass;
	JVM_CP_Class_t *myClassInfo;

	arrayClassIndex = JVM_Opcode_getCodeShort();

	count = JVM_Opcode_popIntValue();

	if (count < 0)
		return (STCD_NEGATIVE_ARRAY_SIZE);

	myStackFrame = JVM_Opcode_getActiveStackFrame();

	myClassInfo = JVM_CPTable_getClassInfo(myStackFrame->currentCpTable,
			arrayClassIndex);
	myClass = myClassInfo->classAdress;

	JVM_Opcode_pushReference(makeReferenceArray(count, myClass));

	/*

	 MemorySize=count*sizeof(JVM_HandleNumber_t);

	 handleNumber=JVM_Handle_newArray(MemorySize,myClass);

	 JVM_Handle_arraySetLenght(handleNumber,count);

	 JVM_Opcode_pushReference(handleNumber);
	 */
	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_multianewarray						Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_multianewarray() {
	uint8_t dimensions;
	uint16_t arrayClassIndex;
	uint16_t counter;
	JVM_Class_t *myClass;
	JVM_CP_Class_t *myClassInfo;
	uint8_t charDataType;
	uint8_t arrayType;

	JVM_CP_UTF8_t *myClassNameUTF8Info;

	arrayClassIndex = JVM_Opcode_getCodeShort();
	dimensions = JVM_Opcode_getCodeByte();

	uint16_t dimensionTable[dimensions + 1];

	myClassInfo = JVM_CPTable_getClassInfo(
			JVM_Opcode_getActiveStackFrame()->currentCpTable, arrayClassIndex);
	myClass = myClassInfo->classAdress;

	myClassNameUTF8Info = JVM_CPTable_getUtf8Info(
			JVM_Opcode_getActiveStackFrame()->currentCpTable, myClassInfo->index);

	counter = 0;

	while (myClassNameUTF8Info->data[counter] == '[') {
		counter++;
	}
	charDataType = myClassNameUTF8Info->data[counter];

	switch (charDataType) {
	case 'B':
		arrayType = T_BYTE;
		break;

	case 'C':
		arrayType = T_CHAR;
		break;

	case 'D':
		arrayType = T_DOUBLE;
		break;

	case 'F':
		arrayType = T_FLOAT;
		break;

	case 'J':
		arrayType = T_LONG;
		break;

	case 'S':
		arrayType = T_SHORT;
		break;

	case 'Z':
		arrayType = T_BOOLEAN;
		break;

	case 'I':
		arrayType = T_INT;
		break;

	case 'L':

		break;

	default:
		return (STCD_UNKNOWN_ARRAY_TYPE);

	}

	for (counter = 0; counter < dimensions; counter++) {
		dimensionTable[dimensions - (counter + 1)] = JVM_Opcode_popIntValue();
	}
	dimensionTable[counter] = 0;

	JVM_Opcode_pushReference(makeMultidimensionalArray(&dimensionTable[0],
			myClass, arrayType)); // TODO Right ArrayType !!!!!

	return (STCD_OK);
}

/****************************************************************************************/
/*																						*/
/*	Function : makeReferenceArray							Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.2.15			Status : Working   			*/
/*																						*/
/****************************************************************************************/
JVM_HandleNumber_t makeMultidimensionalArray(uint16_t * dimensionTable,
		JVM_Class_t *myClass, uint8_t primitiveType) {
	JVM_HandleNumber_t handleNumber;
	int counter;

	if (dimensionTable[1] != 0) {
		handleNumber = makeReferenceArray(dimensionTable[0], myClass);

		for (counter = 0; counter < dimensionTable[0]; counter++) {
			JVM_Handle_arraySetReference(handleNumber, counter,
					makeMultidimensionalArray(&dimensionTable[1], myClass, primitiveType));
		}
	} else {
		handleNumber
				= makePrimitiveArray(dimensionTable[0], myClass, primitiveType);
	}

	return (handleNumber);
}

/****************************************************************************************/
/*																						*/
/*	Function : makeReferenceArray							Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.2.15			Status : Working   			*/
/*																						*/
/****************************************************************************************/
JVM_HandleNumber_t makeReferenceArray(uint16_t count, JVM_Class_t *myClass) {
	uint16_t MemorySize;

	JVM_HandleNumber_t handleNumber;

	MemorySize = count * sizeof(JVM_HandleNumber_t);

	handleNumber = JVM_Handle_newArray(MemorySize, myClass);

	JVM_Handle_arraySetLenght(handleNumber, count);

	return (handleNumber);

}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_arraylength							Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.21.15		Status : Working   			*/
/*																						*/
/****************************************************************************************/

JVM_HandleNumber_t makePrimitiveArray(uint16_t count, JVM_Class_t *myClass,
		uint8_t primitiveType) {

	JVM_HandleNumber_t handleNumber;

	uint16_t MemorySize;

	switch (primitiveType) {
	case T_SHORT:
	case T_CHAR:
		MemorySize = count << 1;
		break;

	case T_INT:
	case T_FLOAT:
		MemorySize = count << 2;
		break;

	case T_LONG:
	case T_DOUBLE:
		MemorySize = count << 3;
		break;

	case T_BOOLEAN:
	case T_BYTE:
		MemorySize = count;
		break;

	default:
		return (STCD_UNKNOWN_ARRAY_TYPE);
	}

	handleNumber = JVM_Handle_newArray(MemorySize, 0); //TODO ClassPointer

	JVM_Handle_arraySetLenght(handleNumber, count);

	return (handleNumber);
}

/****************************************************************************************/
/*																						*/
/*	Function : JVM_cmd_arraylength							Author : OG					*/
/*																						*/
/*	Description : 								   										*/
/*																						*/
/*	Version : 1.0					Date :2011.1.5			Status : Working   			*/
/*																						*/
/****************************************************************************************/

uint16_t JVM_cmd_arraylength() {
	int16_t count;
	JVM_HandleNumber_t handleNumber;

	handleNumber = JVM_Opcode_popIntValue();
	JVM_Handle_arrayGetLenght(handleNumber, &count);
	// Clear Arrays

	JVM_Opcode_pushIntValue(count);
	return (STCD_OK);
}

